import 'dart:convert';

import 'package:flutter/services.dart';
import 'package:tencent_rtc/bridge/trtc_channel_listener.dart';
import 'package:tencent_rtc/trtc_cloud_def.dart';

class TRTCMethodChannel {
  static final TRTCMethodChannel _instance = TRTCMethodChannel._internal();
  static const MethodChannel _channel = MethodChannel("TencentRTCffi");

  TRTCChannelListener? _listener;

  TRTCMethodChannel._internal();

  factory TRTCMethodChannel() => _instance;

  setListener(TRTCChannelListener? listener) {
    _listener = listener;

    if (_listener != null) {
      _channel.setMethodCallHandler((call) async {
        switch (call.method) {
          case "onSnapshotComplete":
            _listener?.handleNativeOnSnapshotComplete != null
                ? _listener?.handleNativeOnSnapshotComplete!(call.arguments)
                : false;
            break;
          default:
            throw MissingPluginException();
        }
      });
    } else {
      _channel.setMethodCallHandler(null);
    }
  }

  Future<void> initialize() async {
    await _channel.invokeMethod('initialize');
  }

  Future<void> startLocalPreview(int viewId) async {
    await _channel.invokeMethod('startLocalPreview', {"viewId": viewId});
  }

  Future<void> startRemoteView(String userId, TRTCVideoStreamType streamType, int viewId) async {
    await _channel.invokeMethod('startRemoteView', {"streamType": streamType.value(), "userId": userId, "viewId": viewId});
  }

  Future<void> stopLocalPreview() async {
    await _channel.invokeMethod('stopLocalPreview', {});
  }

  Future<void> stopRemoteView(String userId, TRTCVideoStreamType streamType) async {
    await _channel.invokeMethod('stopRemoteView', {"userId": userId, "streamType": streamType});
  }

  Future<void> updateLocalView(int viewId) async {
    await _channel.invokeMethod('updateLocalView', {"viewId": viewId});
  }

  Future<void> updateRemoteView(String userId, TRTCVideoStreamType streamType, int viewId) async {
    _channel.invokeMethod('updateRemoteView', {"userId": userId, "streamType": streamType, "viewId": viewId});
  }

  Future<void> snapshotVideo(String userId, TRTCVideoStreamType streamType, TRTCSnapshotSourceType sourceType, String path) async {
    _channel.invokeMethod("snapshotVideo", {
      "userId": userId,
      "streamType": streamType.value(),
      "sourceType": sourceType.value(),
      "path": path,
    });
  }

  Future<void> setVideoMuteImage(String imagePath, int fps) async {
    _channel.invokeMethod("setVideoMuteImage", {
      "imagePath": imagePath,
      "fps": fps,
    });
  }

  Future<void> setWatermark(String imagePath, TRTCVideoStreamType streamType, double x, double y, double width) async {
    _channel.invokeMethod("setWatermark", {
      "imagePath": imagePath,
      "streamType": streamType.value(),
      "x": x,
      "y": y,
      "width": width,
    });
  }

  Future<void> enableVideoProcessByNative(String jsonStr) async {
    final jsonMap = jsonDecode(jsonStr) as Map<String, dynamic>;
    final params = jsonMap['params'] as Map<String, dynamic>? ?? {};
    await _channel.invokeMethod<String>('enableVideoProcessByNative', params);
  }

  Future<void> startScreenCapture(int viewId, TRTCVideoStreamType streamType, TRTCVideoEncParam encParam) async {
    Map<String, dynamic> encParamMap = {
      'videoResolution': encParam.videoResolution.value(),
      'videoResolutionMode': encParam.videoResolutionMode.value(),
      'videoFps': encParam.videoFps,
      'videoBitrate': encParam.videoBitrate,
      'minVideoBitrate': encParam.minVideoBitrate,
      'enableAdjustRes': encParam.enableAdjustRes,
    };
    await _channel.invokeMethod('startScreenCapture', {
      'streamType': streamType.value(),
      'encParam': encParamMap,
    });
  }

  Future<void> startScreenCaptureByReplaykit(TRTCVideoStreamType streamType, TRTCVideoEncParam encParam, String? appGroup) async {
    Map<String, dynamic> encParamMap = {
      'videoResolution': encParam.videoResolution.value(),
      'videoResolutionMode': encParam.videoResolutionMode.value(),
      'videoFps': encParam.videoFps,
      'videoBitrate': encParam.videoBitrate,
      'minVideoBitrate': encParam.minVideoBitrate,
      'enableAdjustRes': encParam.enableAdjustRes,
    };
    await _channel.invokeMethod('startScreenCaptureByReplaykit', {
      'streamType': streamType.value(),
      'encParam': encParamMap,
      'appGroup': appGroup ?? "",
    });
  }

}